package com.wst.system.server.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wst.system.config.exception.GlobalExcetion;
import com.wst.system.security.entity.SysMenuEntity;
import com.wst.system.security.entity.dto.SysMenuEntityListDto;
import com.wst.system.security.entity.dto.SysMenuEntityTreeDto;
import com.wst.system.security.entity.dto.SysMenuEntityTreeMenuDto;
import com.wst.system.security.entity.vo.SysMenuEntityVo;
import com.wst.system.server.mapper.SysMenuMapper;
import com.wst.system.server.service.SysMenuService;
import com.wst.system.util.JSONUtil;
import io.swagger.models.auth.In;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Xiongx
 * @version 1.0
 * @date 2021/6/11 14:48
 * @since JDK 1.8
 */
@Service("sysMenuService")
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity> implements SysMenuService {

    @Override
    public SysMenuEntity saveOrUpdate(SysMenuEntityVo sysMenuEntityVo) throws GlobalExcetion {
        SysMenuEntity sysMenuEntity = new SysMenuEntity();
        BeanUtils.copyProperties(sysMenuEntityVo,sysMenuEntity);
        sysMenuEntity.setName(sysMenuEntityVo.getTitle());
        if(sysMenuEntityVo.getParentId()!=null && sysMenuEntityVo.getParentId()!=0){
            SysMenuEntity sysMenu=super.baseMapper.selectById(sysMenuEntityVo.getParentId());
            if(sysMenu==null){
                throw new GlobalExcetion(1,"父数据不存在");
            }
        }
        if(sysMenuEntityVo.getId()!=null){
            SysMenuEntity entiry=super.baseMapper.selectById(sysMenuEntityVo.getId());
            if(entiry==null){
                throw new GlobalExcetion(1,"数据不存在");
            }
            super.baseMapper.updateById(sysMenuEntity);
        }else{
            super.baseMapper.insert(sysMenuEntity);
        }
        return sysMenuEntity;
    }

    @Override
    public SysMenuEntity getSysMenuEntityByParentId(Integer parentId) {
        LambdaQueryWrapper<SysMenuEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysMenuEntity::getParentId,parentId);
        return this.baseMapper.selectOne(lambdaQueryWrapper);
    }

    @Override
    public IPage<SysMenuEntity> page(Integer pageNum, Integer pageSize, JSONObject search) {
        LambdaQueryWrapper<SysMenuEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(JSONUtil.containsKey(search,"name")){
            lambdaQueryWrapper.like(SysMenuEntity::getName,search.getString("name"));
        }
        lambdaQueryWrapper.orderByDesc(SysMenuEntity::getCreateTime);
        return this.baseMapper.selectPage(new Page(pageNum,pageSize),lambdaQueryWrapper);
    }

    @Override
    public List<SysMenuEntityTreeDto> childList() {
        List<SysMenuEntity> list=super.list();
        List<SysMenuEntityTreeDto> dtoList=new ArrayList<>();
        if(list!=null){
            dtoList=list.stream().map((e)->{
                SysMenuEntityTreeDto dto=new SysMenuEntityTreeDto();
                BeanUtils.copyProperties(e,dto);
                return dto;
            }).collect(Collectors.toList());
            dtoList=buildTree(dtoList);
        }
        return dtoList;
    }

    @Override
    public List<SysMenuEntityTreeMenuDto> childMenuList(List<SysMenuEntity> list) {
        List<SysMenuEntityTreeMenuDto> dtoList=new ArrayList<>();
        if(list!=null){
            dtoList=list.stream().map((e)->{
                SysMenuEntityTreeMenuDto dto=new SysMenuEntityTreeMenuDto();
                BeanUtils.copyProperties(e,dto);
                if(dto.getIcon()!=null){
                    dto.setIcon("fa "+e.getIcon());
                }
                return dto;
            }).collect(Collectors.toList());
            dtoList=buildMenuTree(dtoList);
        }
        return dtoList;
    }


    @Override
    public List<SysMenuEntityListDto> listAll() {
        List<SysMenuEntity> list=super.list();
        List<SysMenuEntityListDto> dtoList=new ArrayList<>();
        if(list!=null){
             dtoList=list.stream().map((e)->{
                SysMenuEntityListDto dto=new SysMenuEntityListDto();
                BeanUtils.copyProperties(e,dto);
                if(dto.getParentId()==0){
                    dto.setParentName("顶级菜单");
                }else {
                    SysMenuEntity parent=list.stream().filter((a)->a.getId()==dto.getParentId()).findFirst().orElse(null);
                    if(parent!=null){
                        dto.setParentName(parent.getName());
                    }
                }
                return dto;
            }).collect(Collectors.toList());
        }
        return dtoList;
    }

    @Override
    public List<SysMenuEntityTreeDto> childList(String name) {
        List<SysMenuEntityTreeDto> dtoList=childList();
        List<SysMenuEntityTreeDto> matchingTrees = new ArrayList<>();
        if(dtoList!=null){
            for (SysMenuEntityTreeDto root : dtoList) {
                SysMenuEntityTreeDto matchedTree = searchTree(root, name);
                if (matchedTree != null) {
                    matchingTrees.add(matchedTree);
                }
            }
        }
        return matchingTrees;
    }

    @Override
    public List<SysMenuEntityTreeDto> childList(List<Integer> childList) {
        List<SysMenuEntity> list=super.list();
        List<SysMenuEntityTreeDto> dtoList=new ArrayList<>();

        Map<Integer, SysMenuEntityTreeDto> dataMap=new HashMap<>();
        for (int i = 0; i < list.size() ; i++) {
            SysMenuEntity sysMenuEntity=list.get(i);
            SysMenuEntityTreeDto dto=new SysMenuEntityTreeDto();
            BeanUtils.copyProperties(sysMenuEntity,dto);
            dataMap.put(sysMenuEntity.getId(), dto);
        }
        for (int i = 0; i < childList.size() ; i++) {
            Integer id=childList.get(i);
            SysMenuEntityTreeDto dto=dataMap.get(id);
            dtoList.add(dto);
        }
        dtoList=buildTree(dtoList,dataMap);
        return dtoList;
    }

    @Override
    public List<SysMenuEntityTreeMenuDto> childMenuListByCid(List<Integer> childList) {
        List<SysMenuEntity> list=super.list();
        List<SysMenuEntityTreeMenuDto> dtoList=new ArrayList<>();

        Map<Integer, SysMenuEntityTreeMenuDto> dataMap=new HashMap<>();
        for (int i = 0; i < list.size() ; i++) {
            SysMenuEntity sysMenuEntity=list.get(i);
            SysMenuEntityTreeMenuDto dto=new SysMenuEntityTreeMenuDto();
            BeanUtils.copyProperties(sysMenuEntity,dto);
            if(dto.getIcon()!=null){
                dto.setIcon("fa "+dto.getIcon());
            }
            dataMap.put(sysMenuEntity.getId(), dto);
        }
        for (int i = 0; i < childList.size() ; i++) {
            Integer id=childList.get(i);
            SysMenuEntityTreeMenuDto dto=dataMap.get(id);
            dtoList.add(dto);
        }
        dtoList=buildTreeMenu(dtoList,dataMap);
        return dtoList;
    }

    public List<SysMenuEntityTreeMenuDto> buildTreeMenu(List<SysMenuEntityTreeMenuDto> childList, Map<Integer, SysMenuEntityTreeMenuDto> dataMap) {
        List<SysMenuEntityTreeMenuDto> sysMenuEntityTreeDtos=new ArrayList<>();
        for (int i = 0; i < childList.size() ; i++) {
            SysMenuEntityTreeMenuDto dto=childList.get(i);
            Integer parentId=dto.getParentId();
            SysMenuEntityTreeMenuDto obj=dto;
            SysMenuEntityTreeMenuDto parent=null;
            while (parentId!=0){
                parent=dataMap.get(parentId);
                if(parent.getChild().size()>0){
                    if(!parent.getChild().contains(obj)){
                        parent.getChild().add(obj);
                    }
                }else {
                    parent.getChild().add(obj);
                }
                parentId=parent.getParentId();
                obj=parent;
                if(parentId==0){
                    if(!sysMenuEntityTreeDtos.contains(parent)){
                        sysMenuEntityTreeDtos.add(parent);
                    }
                }
            }
        }
        return sysMenuEntityTreeDtos;
    }

    // 构建树的方法，返回根节点列表
    public List<SysMenuEntityTreeDto> buildTree(List<SysMenuEntityTreeDto> childList, Map<Integer, SysMenuEntityTreeDto> dataMap) {
        List<SysMenuEntityTreeDto> sysMenuEntityTreeDtos=new ArrayList<>();
        for (int i = 0; i < childList.size() ; i++) {
            SysMenuEntityTreeDto dto=childList.get(i);
            Integer parentId=dto.getParentId();
            SysMenuEntityTreeDto obj=dto;
            SysMenuEntityTreeDto parent=null;
            while (parentId!=0){
                parent=dataMap.get(parentId);
                if(parent.getChildren().size()>0){
                    if(!parent.getChildren().contains(obj)){
                        parent.getChildren().add(obj);
                    }
                }else {
                    parent.getChildren().add(obj);
                }
                parentId=parent.getParentId();
                obj=parent;
                if(parentId==0){
                    if(!sysMenuEntityTreeDtos.contains(parent)){
                        sysMenuEntityTreeDtos.add(parent);
                    }
                }
            }

        }
        return sysMenuEntityTreeDtos;
    }

    private SysMenuEntityTreeDto searchTree(SysMenuEntityTreeDto root,String name){
        // 创建一个新的节点用来保存匹配结果
        SysMenuEntityTreeDto newNode = null;

        // 检查当前节点是否匹配
        if (root.getName().contains(name)) {
            newNode = new SysMenuEntityTreeDto();
            BeanUtils.copyProperties(root,newNode);
            newNode.setChildren(new ArrayList<>());
        }
        // 遍历子节点，寻找匹配
        for (SysMenuEntityTreeDto child : root.getChildren()) {
            SysMenuEntityTreeDto matchedChild = searchTree(child, name);
            if (matchedChild != null) {
                // 如果当前节点匹配，添加子节点到新节点
                if (newNode != null) {
                    newNode.getChildren().add(matchedChild);
                } else {
                    // 如果当前节点不匹配，但有匹配的子节点，创建新节点
                    newNode = new SysMenuEntityTreeDto();
                    BeanUtils.copyProperties(root,newNode);
                    newNode.setChildren(new ArrayList<>());
                    newNode.getChildren().add(matchedChild);
                }
            }
        }

        return newNode;
    }

    public List<SysMenuEntityTreeMenuDto> buildMenuTree(List<SysMenuEntityTreeMenuDto> list){
        Map<Integer, SysMenuEntityTreeMenuDto> nodeMap = new HashMap<>();
        List<SysMenuEntityTreeMenuDto> roots = new ArrayList<>();
        // 将节点添加到映射中
        for (SysMenuEntityTreeMenuDto node : list) {
            nodeMap.put(node.getId(), node);
        }
        // 构建树结构
        for (SysMenuEntityTreeMenuDto node : list) {
            if (node.getParentId() == 0) {
                // 顶级节点
                roots.add(node);
            } else {
                // 非顶级节点，添加到父节点的 children 列表中
                SysMenuEntityTreeMenuDto parentNode = nodeMap.get(node.getParentId());
                if (parentNode != null) {
                    parentNode.getChild().add(node);
                }
            }
        }
        return roots;
    }

    public List<SysMenuEntityTreeDto> buildTree(List<SysMenuEntityTreeDto> list) {
        Map<Integer, SysMenuEntityTreeDto> nodeMap = new HashMap<>();
        List<SysMenuEntityTreeDto> roots = new ArrayList<>();
        // 将节点添加到映射中
        for (SysMenuEntityTreeDto node : list) {
            nodeMap.put(node.getId(), node);
        }
        // 构建树结构
        for (SysMenuEntityTreeDto node : list) {
            if (node.getParentId() == 0) {
                // 顶级节点
                node.setParentName("顶级菜单");
                roots.add(node);
            } else {
                // 非顶级节点，添加到父节点的 children 列表中
                SysMenuEntityTreeDto parentNode = nodeMap.get(node.getParentId());
                if (parentNode != null) {
                    node.setParentName(parentNode.getName());
                    parentNode.getChildren().add(node);
                }
            }
        }
        return roots;
    }
}
